const fs = require('fs').promises;
const path = require('path');
const crypto = require('crypto');
const { execFile } = require('child_process');
const util = require('util');
const execFileAsync = util.promisify(execFile);

async function encryptAndPackage(filePath, authCode) {
  try {
    console.log('Starting encryption process');
    const outputPath = path.join(path.dirname(filePath), 'encrypted-' + path.basename(filePath));
    
    // 只进行一次加密，使用更强的加密方式
    const encryptedPath = await encryption(filePath, authCode);
    process.send({ type: 'progress', progress: 50 });

    // 创建自解压程序
    await createSelfExtractor(encryptedPath, outputPath, authCode);
    process.send({ type: 'progress', progress: 90 });

    // 清理临时文件
    await fs.unlink(encryptedPath).catch(err => 
      console.error('Error deleting encrypted file:', err)
    );

    process.send({ type: 'progress', progress: 100 });
    process.send({ type: 'complete', outputPath: outputPath });
  } catch (error) {
    console.error('Error in encryptAndPackage:', error);
    process.send({ type: 'error', error: error.message });
  }
}

async function encryption(filePath, key) {
  const data = await fs.readFile(filePath);
  const iv = crypto.randomBytes(16);
  const salt = crypto.randomBytes(16);
  const derivedKey = crypto.pbkdf2Sync(key, salt, 100000, 32, 'sha512');
  
  const cipher = crypto.createCipheriv('aes-256-gcm', derivedKey, iv);
  let encrypted = cipher.update(data);
  encrypted = Buffer.concat([
    salt,
    iv,
    encrypted,
    cipher.final(),
    cipher.getAuthTag()
  ]);
  
  const outputPath = filePath + '.enc';
  await fs.writeFile(outputPath, encrypted);
  return outputPath;
}

async function createSelfExtractor(encryptedPath, outputPath, key) {
  const encryptedData = await fs.readFile(encryptedPath);
  const tempScriptPath = path.join(path.dirname(outputPath), 'temp_script.js');

  const scriptContent = `
    const fs = require('fs');
    const crypto = require('crypto');
    const { execFile } = require('child_process');
    const path = require('path');
    const os = require('os');

    const encryptedData = Buffer.from('${encryptedData.toString('base64')}', 'base64');
    
    function decrypt(data, key) {
      const salt = data.slice(0, 16);
      const iv = data.slice(16, 32);
      const authTag = data.slice(-16);
      const encryptedContent = data.slice(32, -16);
      
      const derivedKey = crypto.pbkdf2Sync(key, salt, 100000, 32, 'sha512');
      const decipher = crypto.createDecipheriv('aes-256-gcm', derivedKey, iv);
      decipher.setAuthTag(authTag);
      
      let decrypted = decipher.update(encryptedContent);
      decrypted = Buffer.concat([decrypted, decipher.final()]);
      return decrypted;
    }

    const readline = require('readline').createInterface({
      input: process.stdin,
      output: process.stdout
    });

    readline.question('请输入授权码: ', (key) => {
      readline.close();
      try {
        const decrypted = decrypt(encryptedData, key);
        const tempExePath = path.join(os.tmpdir(), 'dec_' + Date.now() + '.exe');
        fs.writeFileSync(tempExePath, decrypted);
        
        execFile(tempExePath, (error) => {
          if (error) console.error('执行错误:', error);
          try {
            fs.unlinkSync(tempExePath);
          } catch (err) {
            console.error('删除临时文件失败:', err);
          }
        });
      } catch (error) {
        console.error('解密失败，授权码错误');
        process.exit(1);
      }
    });
  `;

  await fs.writeFile(tempScriptPath, scriptContent);

  try {
    await execFileAsync('npx', [
      'pkg',
      tempScriptPath,
      '--target', 'node14-win-x64',
      '--output', outputPath,
      '--compress', 'GZip',
      '--no-bytecode',
      '--public'
    ]);
  } catch (error) {
    throw error;
  } finally {
    await fs.unlink(tempScriptPath).catch(() => {});
  }
}

process.on('message', (message) => {
  encryptAndPackage(message.filePath, message.authCode);
});

process.on('uncaughtException', (error) => {
  process.send({ type: 'error', error: error.message });
});
